package edu.unika.aifb.graphindex.searcher.hybrid.exploration;

/**
 * Copyright (C) 2009 G�nter Ladwig (gla at aifb.uni-karlsruhe.de)
 * 
 * This file is part of the graphindex project.
 *
 * graphindex is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2
 * as published by the Free Software Foundation.
 * 
 * graphindex is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with graphindex.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.unika.aifb.graphindex.searcher.keyword.model.KeywordElement;
import edu.unika.aifb.graphindex.searcher.keyword.model.KeywordSegment;

public class NodeElement extends GraphElement {

	private Set<String> m_inProperties;
	private Set<String> m_outProperties;
	private KeywordSegment keywordSegment;
	private KeywordElement keywordElement;
	
	public NodeElement(String label) {
		super(label);
		m_inProperties = new HashSet<String>();
		m_outProperties = new HashSet<String>();
	}
	
	public KeywordSegment getKeywordSegment() {
		return keywordSegment;
	}

	public void setKeywordSegment(KeywordSegment keywordSegment) {
		this.keywordSegment = keywordSegment;
	}

	public KeywordElement getKeywordElement() {
		return keywordElement;
	}


	public void setKeywordElement(KeywordElement keywordElement) {
		this.keywordElement = keywordElement;
	}


	@Override
	public void reset() {
		super.reset();
		m_inProperties = null;
		m_outProperties = null;
		keywordSegment = null;
	}
	
	public void addInProperties(Set<String> props) {
		if (m_inProperties == null)
			m_inProperties = new HashSet<String>();
		m_inProperties.addAll(props);
	}

	public void addOutProperties(Set<String> props) {
		if (m_outProperties == null)
			m_outProperties = new HashSet<String>();
		m_outProperties.addAll(props);
	}
	
	public void addInProperty(String property) {
		if (m_inProperties == null)
			m_inProperties = new HashSet<String>();
		m_inProperties.add(property);
	}

	public void addOutProperty(String property) {
		if (m_outProperties == null)
			m_outProperties = new HashSet<String>();
		m_outProperties.add(property);
	}
	
	public Set<String> getInProperties(){
		return m_inProperties;
	}
	public Set<String> getOutProperties(){
		return m_outProperties;
	}
	
	public boolean acceptsEdge(EdgeElement edge) {
		if (edge.getTarget() == this && m_inProperties != null && !m_inProperties.contains(edge.getLabel())){
			return false;
		}
		if (edge.getSource() == this && m_outProperties != null && !m_outProperties.contains(edge.getLabel())){
			return false;
		}
		
		return true;
	}

	public double getCost() {
		return m_cost;
	}
	
	public List<GraphElement> getNeighbors(Map<NodeElement,List<EdgeElement>> graph, Cursor cursor, Set<String> keywordEdges) {
		EdgeElement prevEdge = (EdgeElement)(cursor.getParent() != null ? cursor.getParent().getGraphElement() : null);
		Set<GraphElement> parents = cursor.getParents();
		List<GraphElement> neighbors = new ArrayList<GraphElement>();
		
		if (!cursor.isFinished()) {
			for (EdgeElement edge : graph.get(this)) {
				if (!keywordEdges.contains(edge.getLabel())) {
					if (edge.getSource() == this && !edge.getTarget().acceptsEdge(edge)){
						continue;
					}
					if (edge.getTarget() == this && !edge.getSource().acceptsEdge(edge)){
						continue;
					}
				}
				if (!edge.equals(prevEdge) && !parents.contains(edge.getSource()) && !parents.contains(edge.getTarget()))
					neighbors.add(edge);
			}
		}
		
		return neighbors;
	}
	
	public String toString() {
		return m_label + "[" + getCost() + "," + m_keywordCursors.size() + ", " + keywordSegment + "]";
	}
}
